/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.openide; import java.beans.*; import java.lang.reflect.InvocationTargetException; import java.text.MessageFormat; import java.util.ResourceBundle; import javax.swing.JOptionPane; import java.awt.BorderLayout; import javax.swing.JLabel; import javax.swing.JTextField; import javax.swing.border.*; import javax.swing.JPanel; import java.awt.Component; import org.openide.util.NbBundle; /** * This class provides a description of a user notification to be displayed. * * @see TopManager#notify * * @author David Peroutka, Jaroslav Tulach */ public class NotifyDescriptor extends Object { // Property constants /** Name of property for the message to be displayed. */ public static final String PROP_MESSAGE = "message"; // NOI18N /** Name of property for the type of message to use. */ public static final String PROP_MESSAGE_TYPE = "messageType"; // NOI18N /** Name of property for the style of options available. */ public static final String PROP_OPTION_TYPE = "optionType"; // NOI18N /** Name of property for the exact list of options. */ public static final String PROP_OPTIONS = "options"; // NOI18N /** Name of property for the value the user selected. */ public static final String PROP_VALUE = "value"; // NOI18N /** Name of property for the dialog title. */ public static final String PROP_TITLE = "title"; // NOI18N /** Name of property for the detail message reported. */ public static final String PROP_DETAIL = "detail"; // NOI18N // // Properties // /** The message object specifying the message. */ private Object message; /** The message type. */ private int messageType = PLAIN_MESSAGE; /** The option type specifying the user-selectable options. */ private int optionType; /** The option object specifying the user-selectable options. */ private Object[] options; /** The option object specifying the additional user-selectable options. */ private Object[] adOptions; /** The user's choice value object. */ private Object value; /** The title string for the report. */ private String title; /** The object specifying the detail object. */ // private Object detail; /** Property change support. */ private PropertyChangeSupport changeSupport; // // Return values // /** Return value if YES is chosen. */ public static final Object YES_OPTION = new Integer(JOptionPane.YES_OPTION); /** Return value if NO is chosen. */ public static final Object NO_OPTION = new Integer(JOptionPane.NO_OPTION); /** Return value if CANCEL is chosen. */ public static final Object CANCEL_OPTION = new Integer(JOptionPane.CANCEL_OPTION); /** Return value if OK is chosen. */ public static final Object OK_OPTION = new Integer(JOptionPane.OK_OPTION); /** Return value if user closes the window without pressing any button. */ public static final Object CLOSED_OPTION = new Integer(JOptionPane.CLOSED_OPTION); // // Option types // /** Option type used by default. */ public static final int DEFAULT_OPTION = JOptionPane.DEFAULT_OPTION; /** Option type used for negatable confirmations. */ public static final int YES_NO_OPTION = JOptionPane.YES_NO_OPTION; /** Option type used for negatable and cancellable confirmations. */ public static final int YES_NO_CANCEL_OPTION = JOptionPane.YES_NO_CANCEL_OPTION; /** Option type used for cancellable confirmations. */ public static final int OK_CANCEL_OPTION = JOptionPane.OK_CANCEL_OPTION; // // Message types // /** Message type for error messages. */ public static final int ERROR_MESSAGE = JOptionPane.ERROR_MESSAGE; /** Message type for information messages. */ public static final int INFORMATION_MESSAGE = JOptionPane.INFORMATION_MESSAGE; /** Message type for warning messages. */ public static final int WARNING_MESSAGE = JOptionPane.WARNING_MESSAGE; /** Message type for questions. */ public static final int QUESTION_MESSAGE = JOptionPane.QUESTION_MESSAGE; /** Plain message type using no icon. */ public static final int PLAIN_MESSAGE = JOptionPane.PLAIN_MESSAGE; /** Maximum text width to which the text is wrapped */ private static final int MAXIMUM_TEXT_WIDTH = 100; /** * Creates a new notify descriptor with specified information to report. * * If <code>optionType</code> is {@link #YES_NO_OPTION} or {@link #YES_NO_CANCEL_OPTION} * and the <code>options</code> parameter is <code>null</code>, then the options are * supplied by the look and feel. * * The <code>messageType</code> parameter is primarily used to supply a * default icon from the look and feel. * * @param message the object to display * @param title the title string for the dialog * @param optionType indicates which options are available * @param messageType indicates what type of message should be displayed * @param options an array of objects indicating the possible choices * @param initialValue the object that represents the default value * * @see #getMessage * @see #getMessageType * @see #getOptions * @see #getOptionType * @see #getValue */ public NotifyDescriptor(Object message, String title, int optionType, int messageType, Object[] options, Object initialValue) { this.message = message; this.messageType = messageType; this.options = options; this.optionType = optionType; this.title = title; this.value = initialValue; } // // Getters/setters for properties. // /** * Define a descriptive message to be reported. In the most common * usage, the message is just a <code>String</code>. However, the type * of this parameter is actually <code>Object</code>. Its interpretation depends on * its type: * <dl compact> * <dt><code>Object[]</code><dd> A recursively interpreted series of messages. * <dt>{@link Component}<dd> The <code>Component</code> is displayed in the dialog. * <dt>{@link Icon}<dd> The <code>Icon</code> is wrapped in a {@link JLabel} and displayed in the dialog. * <dt>anything else<dd> The {@link Object#toString string representation} of the object. * </dl> * * @param newMessage the <code>Object</code> to report * @see #getMessage */ public void setMessage(Object newMessage) { Object oldMessage = message; message = newMessage; firePropertyChange(PROP_MESSAGE, oldMessage, newMessage); } /** * Get the message object. * @see #setMessage * * @return the <code>Object</code> that is to be reported */ public Object getMessage() { return message; } /** * Define the style of the message. The look and feel manager may lay out * the dialog differently depending on this value, and will often provide * a default icon. The possible values are: * <ul> * <li>{@link #ERROR_MESSAGE} * <li>{@link #INFORMATION_MESSAGE} * <li>{@link #WARNING_MESSAGE} * <li>{@link #QUESTION_MESSAGE} * <li>{@link #PLAIN_MESSAGE} * </ul> * * @param newType the kind of message * * @see #getMessageType */ public void setMessageType(int newType) { if (newType != ERROR_MESSAGE && newType != INFORMATION_MESSAGE && newType != WARNING_MESSAGE && newType != QUESTION_MESSAGE && newType != PLAIN_MESSAGE) throw new IllegalArgumentException( NbBundle.getBundle (NotifyDescriptor.class).getString ("EXC_MessageType") ); int oldType = messageType; messageType = newType; firePropertyChange(PROP_MESSAGE_TYPE, new Integer(oldType), new Integer(messageType)); } /** * Get the message type. * * @return the message type * * @see #setMessageType */ public int getMessageType() { return messageType; } /** * Define the set of options. The option type is used by the look and * feel to determine what options to show (unless explicit options are supplied): * <ul> * <li>{@link #DEFAULT_OPTION} * <li>{@link #YES_NO_OPTION} * <li>{@link #YES_NO_CANCEL_OPTION} * <li>{@link #OK_CANCEL_OPTION} * </ul> * * @param newType the options the look and feel is to display * * @see #getOptionType * @see #setOptions */ public void setOptionType(int newType) { if (newType != DEFAULT_OPTION && newType != YES_NO_OPTION && newType != YES_NO_CANCEL_OPTION && newType != OK_CANCEL_OPTION) throw new IllegalArgumentException(NbBundle.getBundle (NotifyDescriptor.class).getString ("EXC_OptionType")); int oldType = optionType; optionType = newType; firePropertyChange(PROP_OPTION_TYPE, new Integer(oldType), new Integer(optionType)); } /** * Get the type of options that are to be displayed. * * @return the option type * * @see #setOptionType */ public int getOptionType() { return optionType; } /** * Define an explicit description of the set of user-selectable options. * The usual value for the options parameter is an array of * <code>String</code>s. But the parameter type is an array of <code>Object</code>s. Its * interpretation depends on its type: * <dl compact> * <dt>{@link Component}<dd>The component is added to the button row directly. * <dt>{@link Icon}<dd>A {@link javax.swing.JButton} is created with this icon as its label. * <dt>anything else<dd>The <code>Object</code> is {@link Object#toString converted} to a string and the result is used to * label a <code>JButton</code>. * </dl> * * @param newOptions an array of user-selectable options * * @see #getOptions */ public void setOptions(Object[] newOptions) { Object[] oldOptions = options; options = newOptions; firePropertyChange(PROP_OPTIONS, oldOptions, newOptions); } /** * Get the explicit choices the user can make. * @param the array of <code>Object</code>s that give the user's choices * * @see #setOptions */ public Object[] getOptions() { if (options != null) { return (Object[])options.clone (); } return options; } /** * Define an explicit description of the set of additional user-selectable options. * Additional options are supposed to be used for help button, etc. * <P> * The usual value for the options parameter is an array of * <code>String</code>s. But the parameter type is an array of <code>Object</code>s. Its * interpretation depends on its type: * <dl compact> * <dt>{@link Component}<dd>The component is added to the button row directly. * <dt>{@link Icon}<dd>A {@link javax.swing.JButton} is created with this icon as its label. * <dt>anything else<dd>The <code>Object</code> is {@link Object#toString converted} to a string and the result is used to * label a <code>JButton</code>. * </dl> * * @param newOptions an array of user-selectable options * * @see #getOptions */ public void setAdditionalOptions(Object[] newOptions) { Object[] oldOptions = adOptions; adOptions = newOptions; firePropertyChange(PROP_OPTIONS, oldOptions, newOptions); } /** * Get the explicit additional choices the user can make. * @param the array of <code>Object</code>s that give the user's choices * * @see #setOptions */ public Object[] getAdditionalOptions() { if (adOptions != null) { return (Object[])adOptions.clone (); } return null; } /** * Set the value the user has chosen. * You probably do not want to call this yourself, of course. * * @param newValue the chosen value * * @see #getValue */ public void setValue(Object newValue) { Object oldValue = value; value = newValue; firePropertyChange(PROP_VALUE, oldValue, newValue); } /** * Get the value the user has selected. * * @return an <code>Object</code> indicating the option selected by the user * * @see #setValue */ public Object getValue() { return value; } /** * Set the title string for this report description. * * @param newTitle the title of this description * * @see #getTitle */ public void setTitle(String newTitle) { Object oldTitle = title; title = newTitle; firePropertyChange(PROP_TITLE, oldTitle, newTitle); } /** * Get the title string for this report description. * * @return the title of this description * * @see #setTitle */ public String getTitle() { return title; } /** * Define a detail message to be reported. In the most common usage, * this message is just a <code>String</code>. However, the type of this * parameter is actually <code>Object</code>. Its interpretation depends on its type: * <dl compact> * <dt><code>Object[]</code><dd> A recursively interpreted series of messages. * <dt><code>Throwable</code><dd> A stack trace is displayed. * <dt>anything else<dd> The {@link Object#toString string representation} of the object is used. * </dl> * * @param newDetail the detail object of this description * * @see #getDetail * public void setDetail(Object newDetail) { Object oldDetail = detail; detail = newDetail; firePropertyChange(PROP_DETAIL, oldDetail, newDetail); } /** * Get the detail object for this description. * * @return details of this description * * @see #setTitle * public Object getDetail() { return detail; } */ // // Support for reporting bound property changes. // /** * Add a {@link PropertyChangeListener} to the listener list. * * @param listener the <code>PropertyChangeListener</code> to be added */ public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { if (changeSupport == null) { changeSupport = new java.beans.PropertyChangeSupport(this); } changeSupport.addPropertyChangeListener(listener); } /** * Remove a {@link PropertyChangeListener} from the listener list. * * @param listener the <code>PropertyChangeListener</code> to be removed */ public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { if (changeSupport != null) { changeSupport.removePropertyChangeListener(listener); } } /** * Fire a {@link PropertyChangeEvent} to each listener. * * @param propertyName the programmatic name of the property that was changed * @param oldValue the old value of the property * @param newValue the new value of the property */ protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { if (changeSupport != null) { changeSupport.firePropertyChange(propertyName, oldValue, newValue); } } /** * Get the title to use for the indicated type. * @param messageType the type of message * @return the title to use */ protected static String getTitleForType(int messageType) { switch(messageType) { case ERROR_MESSAGE: return NbBundle.getBundle (NotifyDescriptor.class).getString("NTF_ErrorTitle"); case WARNING_MESSAGE: return NbBundle.getBundle (NotifyDescriptor.class).getString("NTF_WarningTitle"); case QUESTION_MESSAGE: return NbBundle.getBundle (NotifyDescriptor.class).getString("NTF_QuestionTitle"); case INFORMATION_MESSAGE: return NbBundle.getBundle (NotifyDescriptor.class).getString("NTF_InformationTitle"); case PLAIN_MESSAGE: return NbBundle.getBundle (NotifyDescriptor.class).getString("NTF_PlainTitle"); } return ""; // NOI18N } /** * Provides information about the results of a command. Offers * no user choices; the user can only acknowledge the message. */ public static class Message extends NotifyDescriptor { /** * Create an informational report about the results of a command. * * @param message the message object * @see NotifyDescriptor#NotifyDescriptor */ public Message(Object message) { this(message, INFORMATION_MESSAGE); } /** * Create a report about the results of a command. * * @param message the message object * @param messageType the type of message to be displayed * @see NotifyDescriptor#NotifyDescriptor */ public Message(Object message, int messageType) { super( message, NotifyDescriptor.getTitleForType(messageType), DEFAULT_OPTION, messageType, new Object[] { OK_OPTION }, OK_OPTION ); } } /** * Provides a description of a possible action and requests confirmation from the user before proceeding. * This should be used to alert the user to a condition * or situation that requires the user's decision before proceeding, such * as an impending action with potentially destructive or irreversible * consequences. It is conventionally in the form of a question: for example, * "Save changes to TestForm?" */ public static class Confirmation extends NotifyDescriptor { /** * Create a yes/no/cancel question with default title. * * @param message the message object * @see NotifyDescriptor#NotifyDescriptor */ public Confirmation(Object message) { this(message, YES_NO_CANCEL_OPTION); } /** * Create a yes/no/cancel question. * * @param message the message object * @param title the dialog title * @see NotifyDescriptor#NotifyDescriptor */ public Confirmation(Object message, String title) { this(message, title, YES_NO_CANCEL_OPTION); } /** * Create a question with default title. * * @param message the message object * @param optionType the type of options to display to the user * @see NotifyDescriptor#NotifyDescriptor */ public Confirmation(Object message, int optionType) { this(message, optionType, QUESTION_MESSAGE); } /** * Create a question. * * @param message the message object * @param title the dialog title * @param optionType the type of options to display to the user * @see NotifyDescriptor#NotifyDescriptor */ public Confirmation(Object message, String title, int optionType) { this(message, title, optionType, QUESTION_MESSAGE); } /** * Create a confirmation with default title. * * @param message the message object * @param optionType the type of options to display to the user * @param messageType the type of message to use * @see NotifyDescriptor#NotifyDescriptor */ public Confirmation(Object message, int optionType, int messageType) { super( message, NotifyDescriptor.getTitleForType(messageType), optionType, messageType, optionType == DEFAULT_OPTION ? new Object[] { OK_OPTION } : null, OK_OPTION ); } /** * Create a confirmation. * * @param message the message object * @param title the dialog title * @param optionType the type of options to display to the user * @param messageType the type of message to use * @see NotifyDescriptor#NotifyDescriptor */ public Confirmation(Object message, String title, int optionType, int messageType) { super( message, title, optionType, messageType, optionType == DEFAULT_OPTION ? new Object[] { OK_OPTION } : null, OK_OPTION ); } } /** * Provides a description of an exception that occurred during * execution of the IDE. */ public static final class Exception extends Confirmation { static final long serialVersionUID =-3387516993124229948L; /** * Create an exception report with default message. * * @param detail the detail object */ public Exception(Throwable detail) { this(detail, detail.getMessage()); // handle InvocationTargetExceptions if (detail instanceof InvocationTargetException) { Throwable target = ((InvocationTargetException)detail).getTargetException(); this.setMessage (target); if (this.getMessage() == null || "".equals(this.getMessage())) { // NOI18N String msg = target.getMessage(); msg = org.openide.util.Utilities.wrapString (msg, MAXIMUM_TEXT_WIDTH, false, false); this.setMessage(msg); } } // emphasize user-non-friendly exceptions if (this.getMessage() == null || "".equals(this.getMessage())) { // NOI18N this.setMessage(MessageFormat.format(NbBundle.getBundle (NotifyDescriptor.class).getString("NTF_ExceptionalException"), new Object[] { detail.getClass().getName() })); this.setTitle(NbBundle.getBundle (NotifyDescriptor.class).getString("NTF_ExceptionalExceptionTitle")); } } /** * Create an exception report. * * @param detail the detail object * @param message the message object */ public Exception(Throwable detail, Object message) { super(message, DEFAULT_OPTION, ERROR_MESSAGE); // customize descriptor // this.setDetail(detail); this.setTitle(NbBundle.getBundle (NotifyDescriptor.class).getString("NTF_ExceptionTitle")); } } /** Notification providing for a line of text input. * @author Dafe Simonek */ public static class InputLine extends NotifyDescriptor { /** * The text field used to enter the input. */ protected JTextField textField; /** Construct dialog with the specified title and label text. * @param text label text * @param title title of the dialog */ public InputLine (final String text, final String title) { this(text, title, OK_CANCEL_OPTION, PLAIN_MESSAGE); } /** Construct dialog with the specified title, label text, option and * message types. * @param text label text * @param title title of the dialog * @param optionType option type (ok, cancel, ...) * @param messageType message type (question, ...) */ public InputLine (final String text, final String title, final int optionType, final int messageType) { super(null, title, optionType, messageType, null, null); super.setMessage(createDesign(text)); } /** * Get the text which the user typed into the input line. * @return the text entered by the user */ public String getInputText () { return textField.getText (); } /** * Set the text on the input line. * @param text the new text */ public void setInputText (final String text) { textField.setText(text); textField.selectAll (); } /** Make a component representing the input line. * @param text a label for the input line * @return the component */ protected Component createDesign (final String text) { JPanel panel = new JPanel(); JLabel textLabel = new JLabel(text); textLabel.setBorder(new EmptyBorder(0, 0, 0, 10)); panel.setLayout(new BorderLayout()); panel.setBorder(new EmptyBorder(10, 10, 6, 6)); panel.add("West", textLabel); // NOI18N panel.add("Center", textField = new JTextField(25)); // NOI18N textField.setBorder(new CompoundBorder(textField.getBorder(), new EmptyBorder(2, 0, 2, 0))); textField.requestFocus(); javax.swing.KeyStroke enter = javax.swing.KeyStroke.getKeyStroke( java.awt.event.KeyEvent.VK_ENTER, 0 ); javax.swing.text.Keymap map = textField.getKeymap (); map.removeKeyStrokeBinding (enter); /* textField.addActionListener (new java.awt.event.ActionListener () { public void actionPerformed (java.awt.event.ActionEvent evt) { System.out.println("action: " + evt); InputLine.this.setValue (OK_OPTION); } } ); */ return panel; } } // end of InputLine } /* * Log * 22 Gandalf 1.21 1/14/00 Jaroslav Tulach #5308 * 21 Gandalf 1.20 1/13/00 Ian Formanek NOI18N * 20 Gandalf 1.19 1/9/00 Jaroslav Tulach NotifyDescription.InputText * selects all text at the beggining so user can easily delete it only by * typing character. * 19 Gandalf 1.18 1/5/00 Jaroslav Tulach * 18 Gandalf 1.17 1/5/00 Jaroslav Tulach Deleted all * NotifyDescriptior constructors that take Icon as argument. * 17 Gandalf 1.16 12/30/99 Jaroslav Tulach Nobody is using * setDetail/getDetail * 16 Gandalf 1.15 12/30/99 Jaroslav Tulach New dialog for * notification of exceptions. * 15 Gandalf 1.14 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 14 Gandalf 1.13 8/17/99 Ian Formanek Generated serial version * UID * 13 Gandalf 1.12 7/1/99 Ian Formanek wrapping of exceptions * 12 Gandalf 1.11 6/8/99 Ian Formanek ---- Package Change To * org.openide ---- * 11 Gandalf 1.10 4/8/99 Ian Formanek Title for Information * message * 10 Gandalf 1.9 4/6/99 Ian Formanek Processes Enter key on * InputLine as OK_OPTION. * 9 Gandalf 1.8 3/30/99 Ian Formanek Fixed additional options * 8 Gandalf 1.7 3/30/99 Jesse Glick [JavaDoc] * 7 Gandalf 1.6 3/29/99 Ian Formanek Added property names * constants * 6 Gandalf 1.5 3/26/99 Ian Formanek Fixed use of obsoleted * NbBundle.getBundle (this) * 5 Gandalf 1.4 3/20/99 Jaroslav Tulach WizardDescriptor changes * 4 Gandalf 1.3 3/3/99 Jesse Glick [JavaDoc] * 3 Gandalf 1.2 2/5/99 Jesse Glick [JavaDoc] * 2 Gandalf 1.1 1/6/99 Jaroslav Tulach * 1 Gandalf 1.0 1/5/99 Ian Formanek * $ */